#pragma once

#include <iostream>
#include <string>
#include <list>
#include <algorithm>
#include <sys/types.h>
#include <sys/socket.h>

#include "InetAddr.hpp"
#include "Log.hpp"

using namespace Log_M;

class User_foundation
{
public:
  virtual void SendTo(int sockfd, const string &message) = 0;
  virtual bool operator==(const InetAddr &u) = 0;
  virtual string id() = 0;
  virtual ~User_foundation() = default;
};

class User : public User_foundation
{
private:
  InetAddr _id;

public:
  User(const InetAddr &id)
      : _id(id) {}

  void SendTo(int sockfd, const string &message) override
  {
    Log(Log_Level::DEBUG) << "send message ";
    int n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.Netaddr(), _id.NetAddrLen());
    (void)n;
  }
  bool operator==(const InetAddr &u) override
  {
    return _id == u;
  }

  string id() override
  {
    return _id.Addr();
  }
  ~User()
  {
  }
};

class User_manger
{
private:
  list<shared_ptr<User_foundation>> _online_user;

public:
  User_manger() {}
  void AddUser(InetAddr &id)
  {
    pthread_mutex_t temp;
    pthread_mutex_init(&temp, nullptr);
    pthread_mutex_lock(&temp);
    for (auto &user : _online_user)
    {
      if (*user == id)
      {
        Log(Log_Level::INFO) << id.Addr() + " 该用户已存在";
        return;
      }
    }
    Log(Log_Level::INFO) << id.Addr() + "是新增的用户";
    _online_user.push_back(make_shared<User>(id));
    pthread_mutex_unlock(&temp);
    pthread_mutex_destroy(&temp);
    PrintUser();
  }

  
  void DelUser(InetAddr &id)
  {
    auto pos = remove_if(_online_user.begin(), _online_user.end(), [&id](shared_ptr<User_foundation> &user)
                         { return *user == id; });
    _online_user.erase(pos, _online_user.end());
    PrintUser();
  }

  void Router(int sockfd, const std::string &message)
  {
    pthread_mutex_t temp;
    pthread_mutex_init(&temp, nullptr);
    pthread_mutex_lock(&temp);
    for (auto &user : _online_user)
    {
      user->SendTo(sockfd, message);
    }
    pthread_mutex_unlock(&temp);
    pthread_mutex_destroy(&temp);
  }

  void PrintUser()
    {
        for(auto user : _online_user)
        {
            Log(Log_Level::DEBUG) <<user->id()+"为在线用户";
        }
    }
  ~User_manger()
  {}
};